unit ChatProtocol.Receiver;

interface

uses Classes, SysUtils;

type
  TStrArray = array of string;

  TChatMessageRec = record
    Sender, IP, Body, FontStr: string;
  end;

  TChatCallRec = record
    Caller, Callee: string;
    CommunicationPort: Integer;
  end;

  TChatRenameRec = record
    OldName, NewName: string;
  end;

  TChatStatusUpdateRec = record
    IsOnline: Boolean;
    User, ForUser, IP: string;
  end;

  TChatDeniedRequest = record
    FromUser, ToUser: string;
  end;

  TChatCommand = record
  private
    class function Explode(const CmdName, S: string; Delim: Char = '/'; Limit: Integer = -1): TStrArray; static;
  public
    class function ChatMessage(const S: string): TChatMessageRec; static;
    class function CallRequest(const S: string): TChatCallRec; static;
    class function RenameRequest(const S: string): TChatRenameRec; static;
    class function StatusUpdate(const S: string): TChatStatusUpdateRec; static;
    class function DeniedRequest(const S: string): TChatDeniedRequest; static;

    class function GenericMessage(Command: string; const S: string; const Separator: Char = '/'): TStrArray; static;
  end;

implementation

{ TChatMessageParser }

class function TChatCommand.CallRequest(const S: string): TChatCallRec;
var
  Params: TStrArray;
begin
  // Formati i pritur:
  //
  // call <derguesi>/<pritesi>/<porta>

  Params := TChatCommand.Explode('call', S);

  Result.Caller := Params[0];
  Result.Callee := Params[1];
  Result.CommunicationPort := StrToIntDef(Params[2], 0);
end;

class function TChatCommand.ChatMessage(const S: string): TChatMessageRec;
var
  Params: TStrArray;
begin
  // Formati i pritur:
  //
  // msg <derguesi>/<IP>/<fonti>/teksti
  //

  // E kufizojme ne 4 maksimumin e array-t
  // ne menyre qe nese useri ka shkruar dicka qe permban
  // slash-in ajo te mos kaloje si element i array-t por si mesazh
  Params := TChatCommand.Explode('msg', S, '/', 4);

  Result.Sender := Params[0];
  Result.IP := Params[1];
  Result.FontStr := Params[2];
  Result.Body := Params[3];
end;

class function TChatCommand.DeniedRequest(const S: string): TChatDeniedRequest;
var
  Params: TStrArray;
begin
  Params := TChatCommand.Explode('reqdenied', S);

  Result.FromUser := Params[0];
  Result.ToUser := Params[1];
end;

class function TChatCommand.Explode(const CmdName, S: string; Delim: Char; Limit: Integer): TStrArray;
var
  List: TStringList;
  I: Integer;

  Dx: Integer;
  Txt: string;
begin
  Txt := Copy(S, Length(CmdName) + 2, MaxInt) + Delim;
  I := 0;

  List := TStringList.Create;
  try
    List.BeginUpdate;

    while Length(Txt) > 0 do
    begin
      Dx := Pos(Delim, Txt);

      List.Add(Copy(Txt, 0, dx - 1));
      Inc(I);

      Txt := Copy(Txt, Dx + 1, MaxInt);

      if I = Limit - 1 then
      begin
        List.Add(Copy(Txt, 0, Length(Txt) - 1));
        Break;
      end;
    end;

    List.EndUpdate;

    SetLength(Result, List.Count);

    for I := 0 to List.Count - 1 do
      Result[I] := List.Strings[I];
  finally
    List.Free;
  end;
end;

class function TChatCommand.GenericMessage(Command: string; const S: string; const Separator: Char = '/'): TStrArray;
begin
  Result := Explode(Command, S, Separator);
end;

class function TChatCommand.RenameRequest(const S: string): TChatRenameRec;
var
  Params: TStrArray;
begin
  // Formati i pritur:
  //
  // ren <emri vjeter>/<emri ri>

  Params := TChatCommand.Explode('rename', S, '/');

  Result.NewName := Params[1];
  Result.OldName := Params[0];
end;

class function TChatCommand.StatusUpdate(const S: string): TChatStatusUpdateRec;
var
  Params: TStrArray;
begin
  // Formati i pritur:
  //
  // st username/for-user/online-offline/ip

  Params := TChatCommand.Explode('st', S, '/');

  Result.User := Params[0];
  Result.ForUser := Params[1];
  Result.IsOnline := Params[2] = '1';
  Result.IP := Params[3];
end;

end.
